import axios, {AxiosInstance} from 'axios';
import {CreateAxiosOptions, HttpConfig, HttpResult, ParamModel} from "/@/utils/http/axios/model/axios-model";
import {HttpCodeEnum, MethodEnum} from "/@/utils/http/axios/enum/method-enum";
import {ElMessage} from "element-plus";

import store from 'store'
//导入进度条插件\js与css
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import {router} from "/@/router";
const cancelToken = axios.CancelToken // 初始化取消请求的构造函数
const pending: any[] = []
const flagMsg: string = 'FASTCLICK'
/**
 * axios请求封装
 */
export class Axios {

    private axiosInstance: AxiosInstance;
    private readonly options: CreateAxiosOptions;

    constructor(options: CreateAxiosOptions) {
        this.options = options;
        this.axiosInstance = axios.create(options);
        //在request拦截器中显示进度条Nprogress.start()
        this.axiosInstance.interceptors.request.use(config => {
            return config
        })
        //response中完成进度条Nprogress.done()
        this.axiosInstance.interceptors.response.use(response => {
            return response
        })
    }


    /**
     * ajax请求
     * @param url
     * @param method
     * @param data
     * @param config
     */
    public httpRequest(url: string, method: MethodEnum, data: object, config?: HttpConfig): Promise<any> {
        config = {
            callBack: () => {
            },
            isHint: true,
            isToken: true,
            ...config
        }
        // 回调函数
        let callBack: Function = config.callBack || function () {
        }
        // 是否提示
        let isHint: Boolean = config.isHint != undefined ? config.isHint : true
        let tokenStr = store.get("token");
        //token获取
        let token = config.isToken ? tokenStr as string : ''
        let params = this.parameterTransition(method, data)
        url = this.urlDispose(url);
        return new Promise((resolve: Function, reject: Function) => {

            this.axiosInstance.request({
                url: url,
                method: method,
                ...params,
                headers: {
                    "Authorization": token
                }
            }).then((res: HttpResult) => {
                this.resultDispose(res, resolve, reject, callBack, isHint)
            }).catch(err => {
                console.error(err)
                ElMessage.error("系统异常,请联系管理员")
                callBack(err)
                reject(err)
            })
        })
    }

    /**
     * 下载请求
     * @param url
     * @param method
     * @param data
     * @param config
     */
    public downloadRequest(url: string, method: MethodEnum, data: object, config?: HttpConfig): Promise<any>{
        config = {
            callBack: () => {
            },
            isHint: true,
            isToken: true,
            ...config
        }
        // 回调函数
        let callBack: Function = config.callBack || function () {
        }
        // 是否提示
        let isHint: Boolean = config.isHint != undefined ? config.isHint : true
        let tokenStr = store.get("token");
        //token获取
        let token = config.isToken ? tokenStr as string : ''
        let params = this.parameterTransition(method, data)
        url = this.urlDispose(url);
        return new Promise((resolve: Function, reject: Function) => {
            this.axiosInstance.request({
                url: url,
                method: method,
                ...params,
                headers: {
                    "Authorization": token
                },
                responseType: 'blob'
            }).then((res: HttpResult) => {
                callBack()
                resolve(res)
            }).catch(err => {
                console.error(err)
                ElMessage.error("系统异常,请联系管理员")
                callBack(err)
                reject(err)
            })
        })
    }


    /**
     * 请求参数转换
     * @private
     */
    private parameterTransition(method: MethodEnum, data: object): ParamModel {
        let params: ParamModel = {
            data: data
        }
        if (method === MethodEnum.GET) {
            params = {
                params: data
            }
        }
        return params
    }


    /**
     * url处理
     * @param url
     * @private
     */
    private urlDispose(url: string): string {
        return import.meta.env.VITE_HTTP_PREFIX + url
    }

    /**
     * http结果返回
     * @param res
     * @private
     */
    private resultDispose(res: HttpResult, resolve: Function, reject: Function, callBack: Function, isHint: Boolean) {
        //回调函数
        callBack(res.data)
        switch (res.data.code) {
            case HttpCodeEnum.SUCCESS:
                if (res.data.msg) {
                    //成功
                    isHint ? ElMessage.success(res.data.msg) : ''
                }
                resolve(res.data.data)
                return
            case HttpCodeEnum.ERROR:
                //错误
                isHint ? ElMessage.error(res.data.msg) : ''
                reject(res)
                return
            case HttpCodeEnum.WARNING:
                isHint ? ElMessage.warning(res.data.msg) : ''
                reject(res.data.data)
                return
            case HttpCodeEnum.NOT_LOGIN:
                isHint ? ElMessage.error(res.data.msg) : ''
                router.push({
                    name: "login"
                })
                return
            default:
                reject(res)
        }

    }

}
